package com.dayuanit.dy17.mix.current;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestPlus {

    private int i;

    private Lock lock = new ReentrantLock();//可重入的锁

    private AtomicInteger ii = new AtomicInteger(0);

    //synchronized 关键字 必须所在某个对象上。如果线程木有抢到锁，则在当前对象上进行排队。
    public synchronized void plus() {
        //局部变量本身就是线程安全的，方法入栈后，会在当前线程栈空间里分配局部变量。
        //也就是说每个线程都会有一个局部变量的拷贝。
//        int i = 0;

        i ++;
    }

    public void plus2() {
        synchronized (this) {
            i ++;
        }
    }

    public void plus3() {
        //手动加锁
//        lock.lock();
        try {
            boolean flag = lock.tryLock(3, TimeUnit.SECONDS);
//            lock.tryLock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            i ++;

        } finally {
            //手动释放锁
            lock.unlock();
        }
    }

    //通过JUC包提供的原子类解决线程安全的问题。原理是：比较交换CAS原理。也就是乐观锁的原理。
    //无锁机制。比较交换。
    public void plus4() {
        ii.addAndGet(1);
    }

    public static void main(String[] args) {
        TestPlus testPlus = new TestPlus();

        new Thread(new Runnable() {
            @Override
            public void run() {
                testPlus.plus();
            }
        }, "t1").start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                testPlus.plus();
            }
        }, "t2").start();

        //synchronized 和 Lock锁都能防止并发，但是有一些区别；
        //synchronized是由虚拟机自动加锁和释放锁；而Lock只能手动的加锁和释放锁
        //synchronized不够灵活，Lock更加灵活。
        //synchronized一旦出现死锁，只能重启。Lock锁提供了tryLock，可以在一定时间范围内得不到锁后，自动返回，能够防止死锁。
        //synchronized无法响应中断信号，Lock锁能够响应中断信号。

    }
}
